/*
 * TcpWritter.cpp
 *
 *  Created on: 2009-8-20
 *      Author: fanliangliang
 */

#include "TcpWritter.h"
#include "SocketListener.h"
#include "TimeoutTimer.h"
#include <xlogger.h>

CTcpWriter* CTcpWriter::NewL(MSocketListener& aListener, RSocket& aSocket) {
	CTcpWriter* self = NewLC(aListener, aSocket);
	CleanupStack::Pop(self);
	return self;
}

CTcpWriter* CTcpWriter::NewLC(MSocketListener& aListener, RSocket& aSocket) {
	CTcpWriter* self = new (ELeave) CTcpWriter(aListener, aSocket);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
}

CTcpWriter::CTcpWriter(MSocketListener& aListener, RSocket& aSocket)
:CActive(EPriorityStandard)
,iListener(aListener)
,iSocket(aSocket)
,iTimer(NULL)
,iTimeout(KDefaultTimeoutInSeconds)
,iIsSending(EFalse) {
	CActiveScheduler::Add(this);
}

CTcpWriter::~CTcpWriter() {
	Cancel();
	delete iTimer;
}

void CTcpWriter::ConstructL() {
	iTimer = CTimeoutTimer::NewL(*this);
}

void CTcpWriter::DoCancel() {
	iSocket.CancelWrite();
	iTimer->Cancel();
	iIsSending = EFalse;
}

void CTcpWriter::RunL() {
	iTimer->Cancel();

	if (iStatus == KErrNone && iIsSending) {
		SendNextPacket();
	}
	else {
		iIsSending = EFalse;
		iListener.OnSocketError(EWriteError);
	}
}

void CTcpWriter::OnTimerExpired() {
	Cancel();
	iIsSending = EFalse;
	iListener.OnSocketError(EWriteTimeout);
}

void CTcpWriter::IssueWrite(const TDesC8& aBuffer) {
	xdump(aBuffer, "Write content, length {%d}", aBuffer.Length());
	
	if (aBuffer.Length() + iTransferBuffer.Length() > iTransferBuffer.MaxLength()) {
		// Not enough space in buffer
		iListener.OnSocketError(EBufferOverflow);
	}
	else {
		// Add new data to buffer
		iTransferBuffer.Append(aBuffer);

		if (!IsActive()) {
			SendNextPacket();
		}
	}
}

void CTcpWriter::SetTimeout(TTimeIntervalSeconds aTimeout) {
	iTimeout = aTimeout;
}

TTimeIntervalSeconds CTcpWriter::Timeout() const {
	return iTimeout;
}

void CTcpWriter::SendNextPacket() {
	if (iTransferBuffer.Length() > 0) {
		// Move data from transfer buffer to actual write buffer
		iWriteBuffer = iTransferBuffer;
		iTransferBuffer.Zero();
		// Initiate actual write
		iSocket.Write(iWriteBuffer, iStatus);

		iIsSending = ETrue;
		// Request timeout
		iTimer->After(iTimeout);
		SetActive();
	}
	else {
		iIsSending = EFalse;
	}
}
